package com.ssy.lingxi.contract.serviceimpl;


import com.ssy.lingxi.contract.entity.SignatureOrganization;
import com.ssy.lingxi.contract.esign.api.SignApi;
import com.ssy.lingxi.contract.esign.constant.EsignApiCode;
import com.ssy.lingxi.contract.esign.constant.EsignConstants;
import com.ssy.lingxi.contract.esign.exception.EsignException;
import com.ssy.lingxi.contract.esign.request.OrgAccountCreateRequest;
import com.ssy.lingxi.contract.esign.request.OrgAccountUpdateRequest;
import com.ssy.lingxi.contract.esign.request.PersonalSealCreateRequest;
import com.ssy.lingxi.contract.esign.response.*;
import com.ssy.lingxi.contract.model.constant.CommonBooleanEnum;
import com.ssy.lingxi.contract.repository.SignatureOrganizationRepository;
import com.ssy.lingxi.contract.service.ISignatureOrganizationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.Optional;

/**
 * 签章机构信息服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2020/9/1
 */
@Slf4j
@Service
public class SignatureOrganizationServiceImpl implements ISignatureOrganizationService {

    @Resource
    private SignatureOrganizationRepository signatureOrganizationRepository;
    @Resource
    private SignApi signApi;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String createAccount(String accountId, String orgCode, String orgName, String legalIdNumber, String legalName, String legalMobile) throws EsignException {
        // 查询系统是否留存账户信息
        SignatureOrganization organization = signatureOrganizationRepository.findByIdNumber(orgCode);
        if (Objects.nonNull(organization)) {
            // 校验信息是否一致
            if (!verifyMessage(organization, orgName, legalName, legalIdNumber)) {
                // 修改账号信息,如果已实名,将会变成未实名
                OrgAccountUpdateRequest updateAccountRequest = OrgAccountUpdateRequest.builder()
                        .orgId(organization.getOrgId())
                        .name(organization.getName())
                        .orgLegalName(legalName)
                        .orgLegalIdNumber(legalIdNumber)
                        .build();
                OrgAccountUpdateResponse updateAccountResponse = signApi.account().orgAccountUpdate(updateAccountRequest);

                // 更新留存信息
                organization.setName(updateAccountResponse.getName());
                organization.setOrgLegalName(legalName);
                organization.setOrgLegalIdNumber(legalIdNumber);
                organization.setOrgLegalMobile(legalMobile);
                organization.setState(CommonBooleanEnum.NO.getCode());
                organization.setSilent(CommonBooleanEnum.NO.getCode());
            }

            // 返回机构账户id
            return organization.getOrgId();
        }

        SignatureOrganization signatureOrganization = createAccountIfAbsent(accountId, orgCode, orgName, legalIdNumber, legalName, legalMobile);
        signatureOrganizationRepository.saveAndFlush(signatureOrganization);

        return signatureOrganization.getOrgId();
    }

    /**
     * 如果存在账号则更新, 不存在则创建
     * @param accountId 个人账号id
     * @param orgCode 组织账号id
     * @param orgName 组织名称
     * @param legalIdNumber 法人身份证
     * @param legalName 法人姓名
     * @param legalMobile 法人手机号
     * @return 返回结果
     */
    private SignatureOrganization createAccountIfAbsent(String accountId, String orgCode, String orgName, String legalIdNumber, String legalName, String legalMobile) throws EsignException {
        SignatureOrganization signatureOrganization = new SignatureOrganization();
        try {
            // 创建机构账号
            OrgAccountCreateRequest oacRequest = OrgAccountCreateRequest.builder()
                    .thirdPartyUserId(orgCode)
                    .creator(accountId)
                    .idType(EsignConstants.orgIdType.CRED_ORG_USCC)
                    .name(orgName)
                    .idNumber(orgCode)
                    .orgLegalName(legalName)
                    .orgLegalIdNumber(legalIdNumber)
                    .build();

            OrgAccountCreateResponse oacResponse = signApi.account().orgAccountCreate(oacRequest);

            signatureOrganization.setOrgId(oacResponse.getOrgId());
            signatureOrganization.setName(orgName);
            signatureOrganization.setIdNumber(orgCode);
            signatureOrganization.setIdType(EsignConstants.orgIdType.CRED_ORG_USCC);
            signatureOrganization.setCreator(accountId);
            signatureOrganization.setOrgLegalName(legalName);
            signatureOrganization.setOrgLegalIdNumber(legalIdNumber);
            signatureOrganization.setOrgLegalMobile(legalMobile);
            signatureOrganization.setState(CommonBooleanEnum.NO.getCode());
            signatureOrganization.setSilent(CommonBooleanEnum.NO.getCode());
        } catch (EsignException e) {
            // 如果接口返回报错,返回码是账户已存在,则查询账户信息
            if (EsignApiCode.ACCOUNT_EXISTS.equals(e.getError().getErrCode())) {
                OrgAccountDetailResponse oadResponse = signApi.account().orgAccountByThirdId(orgCode);
                signatureOrganization.setName(oadResponse.getName());
                signatureOrganization.setIdNumber(oadResponse.getIdNumber());
                signatureOrganization.setIdType(EsignConstants.orgIdType.CRED_ORG_USCC);
                signatureOrganization.setCreator(accountId);
                signatureOrganization.setOrgLegalName(oadResponse.getOrgLegalName());
                signatureOrganization.setOrgLegalIdNumber(oadResponse.getOrgLegalIdNumber());
                signatureOrganization.setOrgLegalMobile(legalMobile);
                signatureOrganization.setState(Optional.ofNullable(oadResponse.getStatus()).filter(status -> status).map(status -> CommonBooleanEnum.YES.getCode()).orElse(CommonBooleanEnum.NO.getCode()));
            } else {
                // 其他未知异常向上抛
                throw e;
            }
        }

        // 查询个人印章
        SealDetailResponse sealDetailResponse = signApi.seal().organizationSealDetail(signatureOrganization.getOrgId());
        if (sealDetailResponse.getTotal() > 0) {
            // 有个人印章,则保存
            String sealId = Optional.ofNullable(sealDetailResponse.getSeals()).map(list -> list.get(0).getSealId()).orElse("");
            signatureOrganization.setSealId(sealId);
        } else {
            // 没有个人印章,则创建
            PersonalSealCreateRequest personalSealCreateRequest = PersonalSealCreateRequest.builder()
                    .accountId(signatureOrganization.getOrgId())
                    .color(EsignConstants.SealColor.RED)
                    .type(EsignConstants.SealPersonalType.SQUARE)
                    .build();
            PersonalSealCreateResponse pscResponse = signApi.seal().personalSealCreate(personalSealCreateRequest);
            signatureOrganization.setSealId(pscResponse.getSealId());
        }

        return signatureOrganization;
    }

    /**
     * 比较留存信息
     * @param account 机构信息
     * @param orgName 名称
     * @param legalName 法人名称
     * @param legalIdNumber 法人身份证号
     * @return 返回结果
     */
    private boolean verifyMessage(SignatureOrganization account, String orgName, String legalName, String legalIdNumber) {
        return account.getName().equals(orgName)
                && account.getOrgLegalName().equals(legalName)
                && account.getOrgLegalIdNumber().equals(legalIdNumber);
    }
}